New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create parser plugin "topLevelAwait" #10449
Conversation
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/11589/ |
Awesome! Should we add something like a flag using babel/packages/babel-preset-env/src/index.js Lines 160 to 166 in fcb77de
|
We can do it when we have |
d7ba3c6
to
371115b
Compare
The failing test262 tests are fixed by tc39/test262#2388 |
371115b
to
5f07ea2
Compare
@@ -2183,6 +2183,7 @@ export default class ExpressionParser extends LValParser { | |||
isAwaitAllowed(): boolean { | |||
if (this.scope.inFunction) return this.scope.inAsync; | |||
if (this.options.allowAwaitOutsideFunction) return true; | |||
if (this.hasPlugin("topLevelAwait")) return this.inModule; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If top-level await is only valid in modules, should seeing one set sawUnambiguousESM
? In other words, how should this behave with a sourceType
of unambiguous
? Currently, parsing await 0
with unambiguous
yields an AST with sourceType
of script
, even though if you'd specified script
it would not have parsed:
> require('./').parse('await 0', { plugins: ['topLevelAwait'], sourceType: 'unambiguous' }).program.sourceType
'script'
> require('./').parse('await 0', { plugins: ['topLevelAwait'], sourceType: 'script' }).program.sourceType
Thrown:
{ [SyntaxError: Unexpected token, expected ";" (1:6)
] pos: 6, loc: Position { line: 1, column: 6 } }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is tricky because, for exmaple, this is both a valid script and a valid module:
await
0
I can set it to a module when await
the next invalid token is on the same line.
c9112da
to
00b0989
Compare
00b0989
to
94cfa86
Compare
"column": 7 | ||
} | ||
}, | ||
"sourceType": "script", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a script that contains an await expression? I thought that wasn’t allowed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We allow it using the allowAwaitOutsideFunction
option, but it's not in the spec.
It's used, for example, by @babel/template
users who might then wrap it in an async function.
@@ -2234,9 +2235,18 @@ export default class ExpressionParser extends LValParser { | |||
); | |||
} | |||
|
|||
if (!this.scope.inFunction && !this.options.allowAwaitOutsideFunction) { | |||
if (this.hasPrecedingLineBreak()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the following examples are also ambiguous
await + 0
await - 0
await ( 0 )
await [ 0 ]
await / 0 /u
I am not sure if they are complete but we can always lookahead charcode to fix them.
this.match(tt.plusMin) || | ||
this.match(tt.parenL) || | ||
this.match(tt.bracketL) || | ||
this.match(tt.backQuote) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! I missed await ` 0 `
.
I come up with a new case: If one turns on v8intrinsic
, the following could be ambiguous, too.
await %a()
I was initially going to add an |
Co-Authored-By: Brian Ng <bng412@gmail.com>
Fixes #1, Fixes #2
It is a Stage 3 proposal: https://github.com/tc39/proposal-top-level-await
This is different from the
allowAwaitOutsideFunction
because the top-level-await proposal only allows it in modules, whileallowAwaitOutsideFunction
also allows it in scripts. Also, I think that we need the plugin rather than the option for consistency with all the other plugins.Ref: babel/proposals#44, #7637